{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# List\n",
    "\n",
    "\n",
    "\n",
    "## 1 The list is a sequence\n",
    "\n",
    "Like a tuple,a **list** is an <b>ordered sequence</b> of values, where each value is <b>identified by an index </b>. \n",
    "\n",
    "The syntax for expressing literals of type list is similar to that used for tuples; \n",
    "\n",
    "the difference is that we use square brackets <b style=\"color:blue\">[ ]</b> rather than parentheses(). \n",
    "\n",
    "As with tuples, a **for** statement can be used to iterate over the elements of a list.\n",
    "\n",
    "So, for example, the code,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I did it all\n",
      "4\n",
      "love\n"
     ]
    }
   ],
   "source": [
    "L = ['I did it all', 4, 'love']  # square brackets []\n",
    "\n",
    "for li in L:\n",
    "    print(li)    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I did it all\n",
      "4\n",
      "love\n"
     ]
    }
   ],
   "source": [
    "for i in range(len(L)):\n",
    "    print(L[i])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The <b>empty list</b> is written as <b style=\"color:blue\">[]</b>\n",
    "\n",
    "**Singleton lists** are written <b>without comma</b> before the closing bracket."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "empty list: []\n",
      "<class 'list'>\n",
      "[10]\n"
     ]
    }
   ],
   "source": [
    "Lempty=[]   #empty list\n",
    "\n",
    "Lonly1=[10] # singleton list: without comma\n",
    "\n",
    "print('empty list:',Lempty)\n",
    "\n",
    "print(type(Lonly1))\n",
    "print(Lonly1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Occasionally, the fact that Square brackets  $[]$ are used for \n",
    "\n",
    "* 1 **literals** of type list\n",
    "\n",
    "* 2 **indexing** into lists, and\n",
    "\n",
    "* 3 **slicing** lists\n",
    "\n",
    "can lead to some `visual confusion`. \n",
    "\n",
    "For example:the expression `[1,2,3,4][1:3][1]`, which evaluates to 3, uses the square brackets in three different ways. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "[2, 3]\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "L1=[1,2,3,4]\n",
    "print(L1)  #  literals of typel ist\n",
    "\n",
    "print(L1[1:3]) # slicing list\n",
    "\n",
    "print(L1[1:3][1]) # licing list,then indexing into sliced list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "This is rarely a problem in practice, because most of the time lists are `built incrementally` rather than `written as literals`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 lists are` mutable`\n",
    "\n",
    "Lists differ from tuples in one hugely important way: <b style=\"color:blue\">lists are mutable</b>\n",
    "\n",
    "**tuples and strings** are `immutable`\n",
    "\n",
    "* the objects of `immutable` types **cannot be modified `after they are created`**.\n",
    "\n",
    "**lists are` mutable`**\n",
    "\n",
    "* The `list` **can be modified `after they are created`**.\n",
    "\n",
    "Mutating an object: `modify in place` without creating a new object\n",
    "\n",
    "When the bracket operator[] appears on the left side of an assignment, it identifies the element of the list that will be assigned."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['I did it all', 5, 'love']"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = ['I did it all', 4, 'love'] \n",
    "L[1] = 5\n",
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Append , concatenation(+)  and extend list\n",
    "\n",
    "### append\n",
    "\n",
    "`append` one list  to another, the `original structure is `**maintained**. \n",
    "\n",
    "**mutated** L1.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1958540199560\n",
      "[1, 2, 3, [4, 5, 6]]\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "L2 = [4,5,6]\n",
    "print(id(L1))\n",
    "L1.append(L2)\n",
    "print(L1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[1, 2, 3, 4, 5, 6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L1.append(L2),L1 = [1, 2, 3, [4, 5, 6]]\n",
      "mutated L1:id L1.append(L2)= 2049676936128\n"
     ]
    }
   ],
   "source": [
    "print('L1.append(L2),L1 =', L1)\n",
    "print('mutated L1:id L1.append(L2)=',id(L1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**`append` one `item` to the `list`, the `original structure is maintained`.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "i1 = 4\n",
    "L1.append(i1)\n",
    "print(L1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, (4, 5, 6)]\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "t2 = (4,5,6)\n",
    "L1.append(t2)\n",
    "print(L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since `lists` are **mutable**, they can be **constructed incrementally** during a computation.\n",
    "\n",
    "For example, the following code incrementally builds a list containing all of the `even` numbers in another list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-2, 4]\n"
     ]
    }
   ],
   "source": [
    "L=[1, -2, 3.33,4]\n",
    "evenElems = []\n",
    "for e in L:\n",
    "    if e%2 == 0:\n",
    "        evenElems.append(e)\n",
    "        \n",
    "print(evenElems)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Concatenating lists：+ \n",
    " \n",
    "the operator(concatenation): `+` does not have a side effect. \n",
    "\n",
    "It creates **a new list** and returns it. \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L3= L1 + L2,L3  [1, 2, 3, 4, 5, 6]\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "L2 = [4,5,6]\n",
    "\n",
    "#  +  creates a new list\n",
    "L3 = L1 + L2 \n",
    "print('L3= L1 + L2,L3 ', L3)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "append [1, 2, 3, [4, 5, 6]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id L1= 2049677889472\n",
      "id L2= 2049678101632\n",
      "a new list:id L3= 2049678101888\n"
     ]
    }
   ],
   "source": [
    "\n",
    "print('id L1=',id(L1))\n",
    "print('id L2=',id(L2))\n",
    "print('a new list:id L3=',id(L3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Combining lists：extend\n",
    "\n",
    "If you have a list already defined, you can append multiple `elements` to it using the `extend` method:\n",
    "\n",
    "**mutated** L1.\n",
    "\n",
    "* add items in the `list` L2 to the end of list L1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L1.extend(L2) ,L1 = [1, 2, 3, 4, 5, 6]\n"
     ]
    }
   ],
   "source": [
    "# extend : add items in the list L2 to the end of list L1\n",
    "L1 = [1,2,3]\n",
    "L2 = [4,5,6]\n",
    "L1.extend(L2) # 1\n",
    "print('L1.extend(L2) ,L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* append [1, 2, 3, [4, 5, 6]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mutated L1: id L1.extend(L2)= 2049678100864\n"
     ]
    }
   ],
   "source": [
    "print('mutated L1: id L1.extend(L2)=',id(L1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* add **items** in `tuple` t2  to the end of list L1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L1.extend(L2) ,L1 = [1, 2, 3, 4, 5, 6]\n",
      "mutated L1: id L1.extend(L2)= 2049677866112\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "t2 = (4,5,6)\n",
    "L1.extend(t2) # 1\n",
    "print('L1.extend(L2) ,L1 =', L1)\n",
    "print('mutated L1: id L1.extend(L2)=',id(L1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* add items in `string` str2  to the end of list L1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L1.extend(L2) ,L1 = [1, 2, 3, '4', '5', '6']\n",
      "mutated L1: id L1.extend(L2)= 2049676936128\n"
     ]
    }
   ],
   "source": [
    "L1 = [1,2,3]\n",
    "str2 = \"456\"\n",
    "L1.extend(str2) # 1\n",
    "print('L1.extend(L2) ,L1 =', L1)\n",
    "print('mutated L1: id L1.extend(L2)=',id(L1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4 The List's Operators and Methods\n",
    "\n",
    "* Common Operators and Functions with Sequence Types \n",
    "\n",
    "* Common Operators and Functions with Sequence Types \n",
    "\n",
    "https://docs.python.org/tutorial/datastructures.html#more-on-lists"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1 Common Operators and Functions with Sequence Types "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "L=[1,3,5,3,6,7]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "5 in L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "5 not in L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L.count(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L.index(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Slicing\n",
    "\n",
    ">Recap:\n",
    "> [Unit1-1-INTRODUCTION_TO_PYTHON: Slicing String](./Unit1-1-INTRODUCTION_TO_PYTHON.ipynb)\n",
    ">\n",
    ">**Strings are one of several sequence types in Python** \n",
    ">\n",
    ">**They `share` the following operations with `all sequence` types.**\n",
    ">\n",
    ">* **Slicing** is used to extract substrings of arbitrary length. If s is a string, the expression <b>s[start:end] </b> denotes the >substring of s that starts at index `start` and ends at index <b>end-1</b>.\n",
    "\n",
    "You can select sections of most sequence types by using slice notation, which in its basic form consists of `start:stop` passed to the indexing operator `[]`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 7, 5]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n",
    "seq[1:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Slices can also be `assigned` to with a sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n",
    "seq[3:4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**list is mutable**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[7, 2, 3, 6, 3, 5, 6, 0, 1]"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seq[3:4] = [6, 3]\n",
    "seq"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "the element of seq[3:4] `[7]` is replaces by the  `[6, 3]`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "While the element at the `start` index is `included`, the `stop` index is `not included`, so that the number of elements in the result is `stop - start`.\n",
    "\n",
    "Either `the start or stop can be omitted`, in which case they default to the start of the sequence and the end of the sequence, respectively:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "the start is omitted "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n",
    "seq[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "the stop is omitted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq[3:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Negative` indices slice the sequence `relative to the end`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n",
    "seq[-4:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq[-6:-2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Last item"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq[-1:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A `step` can also be used after a second colon to, say, take `every other` element:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n",
    "seq[::2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A clever use of this is to pass -1, which has the useful effect of reversing a list or tuple:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq[::-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.2 Common List Operators and Functions(mutable Sequences) :\n",
    "\n",
    "* `Assignment` via [i], [-i] (indexing) and [m:n:step] (slicing)\n",
    "\n",
    "* `Assignment` via =, += (compound concatenation), *= (compound repetition)\n",
    "\n",
    "* del L[i]: delete the item at index i in L \n",
    "\n",
    "* L.clear(), remove all the items from the lst and return None; same as del L[:].\n",
    "\n",
    "* L.remove(e),  deletes the first occurrence of e from L\n",
    "\n",
    "* L.append(e), adds the **object** e to the end of L.\n",
    "\n",
    "* L1.extend(L2), adds **items** in the list L2 to the end of list L1\n",
    "\n",
    "* L.insert(i, e), inserts the object e into L at index i.\n",
    "\n",
    "* L.pop(i), removes and returns the item at index i; i defaults to -1. Raises IndexError if L\n",
    "is empty.\n",
    "\n",
    "* L.copy(): return a copy of L; same as L[:]\n",
    "\n",
    "* L.reverse(): has the side effect of reversing the order of the elements in L.\n",
    "\n",
    "* L.sort(): arranges the elements of the list from low to high.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using `insert` you can insert an element at a specific `location` in the list:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 'red', 2, 3]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = [1,2,3]\n",
    "L.insert(1, 'red')\n",
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The insertion index must be between `0 and the length of the list`, inclusive.\n",
    "\n",
    "The inverse operation to insert is `pop`, which `removes` and returns `an element` at a particular `index`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L.pop(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 'red', 3]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`Elements` can be `removed` by `value` with **remove**, which locates the `first such value` and removes it from the last:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 'red']"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = [1,2,'red',3,'red']\n",
    "L.remove('red')\n",
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### sort\n",
    "You can sort a list `in-place (without creating a new object)` by calling its `sort` function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 5, 7]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [7, 2, 5, 1, 3]\n",
    "a.sort()\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`sort` has a few options that will occasionally come in handy. One is the ability to pass a secondary sort **key**—that is, `a function` that produces a value to use to sort the objects.\n",
    "\n",
    "For example, we could sort a collection of strings by their `lengths`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['He', 'saw', 'six', 'small', 'foxes']"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = ['saw', 'small', 'He', 'foxes', 'six']\n",
    "b.sort(key=len)\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### reverse\n",
    "\n",
    "reverse the order of element in L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['foxes', 'small', 'six', 'saw', 'He']"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.reverse()\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3, 7, 2, 1]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L=[1,2,7,3]\n",
    "L.reverse()\n",
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5 Aliasing(别名)\n",
    "\n",
    "### 5.1 Aliasing\n",
    "Consider the code,it `mutates` the lists"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tech ['USA-MIT', 'Caltech']\n",
      "USATechs ['USA-MIT', 'Caltech']\n"
     ]
    }
   ],
   "source": [
    "Techs = ['MIT', 'Caltech']\n",
    "\n",
    "# through the variable USATechs\n",
    "USATechs=Techs  # create the aliase of Techs \n",
    "\n",
    "USATechs[0]='USA-MIT'\n",
    "\n",
    "#Techs[0]='USA-MIT'\n",
    "\n",
    "print(\"Tech\",Techs)\n",
    "print(\"USATechs\",USATechs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['MIT', 'Caltech']\n",
      "['MIT', 'Caltech']\n"
     ]
    }
   ],
   "source": [
    "# through the variable Techs\n",
    "Techs[0]='MIT'\n",
    "print(Techs)\n",
    "#USATechs[0]='USA-MIT'\n",
    "print(USATechs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2049678126848\n",
      "2049678126848\n",
      "2049678126848\n"
     ]
    }
   ],
   "source": [
    "print(id(Techs))\n",
    "print(id(USATechs))\n",
    "addnewname=Techs\n",
    "print(id(Techs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is  called **aliasing**(别名). \n",
    "\n",
    "There are `two distinct paths` to the `same` list object\n",
    "\n",
    "* One path is through the variable `USATechs`\n",
    "\n",
    "* the other is through the variable `Techs`\n",
    "\n",
    "One can `mutate` the object via `either` path, and the effect of the `mutation` will be visible through both paths. \n",
    "\n",
    "**Unintentional `aliasing` leads to programming errors that are often enormously hard to track down**.\n",
    "\n",
    "**varibale: name is not the object,it is the refernce to the object**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.2 Variable and Objects\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "a=1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1 is the object，integer type\n",
    "* a is the name of object 1\n",
    "\n",
    "An assignment statement: associates the `name` with `an object`\n",
    "\n",
    "```python\n",
    "Variable(the name of object)=object\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 5.2.1  Objects\n",
    "\n",
    "**Objects** are the core things that Python programs manipulate. Every object has a **type** that defines the kinds of things that programs can do with objects of that type.\n",
    "\n",
    "#### 5.2.2   A variable is just a name of object\n",
    " \n",
    "Python is `dynamically typed`, which means that **a variable** is **just a name of an `object`**.\n",
    "\n",
    "* `Variables`  is not the object"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An object can have `one`, `more than one`, or `no` **name** associated with it.\n",
    "\n",
    "\n",
    "><b style=\"color:blue\">id(object)</b>\n",
    ">\n",
    ">Return the `“identity”` of an object. This is an integer which is guaranteed to be `unique and constant` for this object during its lifetime.\n",
    "\n",
    "\n",
    "For example: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 2337 id x  2049678219024\n",
      " 2338 id x  2049678219536\n",
      " 2338 id y  2049678219536\n"
     ]
    }
   ],
   "source": [
    "# x is the name of the object 2337\n",
    "x=2337\n",
    "print(\" 2337 id x \",id(x))\n",
    "\n",
    "# x is the name of  the object 2338\n",
    "x=2338\n",
    "# y is the name of  the object 2338\n",
    "y=x\n",
    "print(\" 2338 id x \",id(x))\n",
    "print(\" 2338 id y \",id(y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Variables `x,y` are `2338`'s `names`’- **more than one name**\n",
    "\n",
    "* object: 2338 \n",
    "\n",
    "* names of the object: 2338: `x,y` \n",
    "\n",
    "![](./img/python-name.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In dynamic languages,**variable names are stored in memory** while the program runs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(locals())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6 Cloning\n",
    "\n",
    "It is usually prudent to **avoid mutating a list over which one is `iterating`**.\n",
    "\n",
    "Consider, for example, the code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current Item= 1\n",
      "Current len(L1)= 4\n",
      "L1= [1, 2, 3, 4] \n",
      "\n",
      "Current Item= 3\n",
      "Current len(L1)= 3\n",
      "L1= [2, 3, 4] \n",
      "\n",
      "Current Item= 4\n",
      "Current len(L1)= 3\n",
      "L1= [2, 3, 4] \n",
      "\n",
      "\n",
      " removeDups L1 = [2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "def removeDups(L1, L2):\n",
    "    \"\"\"Assumes that L1 and L2 are lists.\n",
    "       Removes any element from L1 that also occurs in L2\"\"\"\n",
    "    for e1 in L1:\n",
    "       \n",
    "        # display mutation：L1.remove(e1)\n",
    "        print('Current Item=',e1) \n",
    "        print('Current len(L1)=',len(L1))  \n",
    "       \n",
    "        print('L1=',L1,'\\n')\n",
    "        \n",
    "        if e1 in L2:\n",
    "            L1.remove(e1) # mutation：L1.remove(e1)\n",
    "\n",
    "L1 = [1,2,3,4]\n",
    "L2 = [1,2,5,6]\n",
    "\n",
    "removeDups(L1, L2)\n",
    "# 1,2\n",
    "# L1=[3,4]\n",
    "print('\\n removeDups L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.1 Slicing to clone \n",
    "\n",
    "make a copy of the list and write \n",
    "     \n",
    "```python     \n",
    "     for e1 in L1[:]:\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current Item= 1\n",
      "Current len(L1)= 4\n",
      "L1= [1, 2, 3, 4] \n",
      "\n",
      "Current Item= 3\n",
      "Current len(L1)= 3\n",
      "L1= [2, 3, 4] \n",
      "\n",
      "Current Item= 4\n",
      "Current len(L1)= 3\n",
      "L1= [2, 3, 4] \n",
      "\n",
      "\n",
      " removeDups L1 = [2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "def removeDups(L1, L2):\n",
    "    \"\"\"Assumes that L1 and L2 are lists.\n",
    "       Removes any element from L1 that also occurs in L2\"\"\"\n",
    " \n",
    "    for e1 in L1[:]: # use slicing to clone\n",
    "        \n",
    "        print('Current Item=',e1) \n",
    "        print('Current len(L1)=',len(L1))  \n",
    "       \n",
    "        print('L1=',L1,'\\n')\n",
    "        \n",
    "        if e1 in L2:\n",
    "            L1.remove(e1)\n",
    "\n",
    "L1 = [1,2,3,4]\n",
    "L2 = [1,2,5,6]\n",
    "removeDups(L1, L2)\n",
    "print('\\n removeDups L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b style=\"color:red\">newL1 = L1</b> merely have introduced <b style=\"color:red\">a new name for L1</b>\n",
    "\n",
    "* Assignment statements in Python do not copy objects, they create bindings between a target and an object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "L1= [1, 2, 3, 4]\n",
      "3\n",
      "L1= [2, 3, 4]\n",
      "3\n",
      "L1= [2, 3, 4]\n",
      "\n",
      " removeDups L1 = [2, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "def removeDups(L1, L2):\n",
    "    \"\"\"Assumes that L1 and L2 are lists.\n",
    "       Removes any element from L1 that also occurs in L2\"\"\"\n",
    "    \n",
    "    newL1=L1  # Assignment statements in Python do not copy objects, \n",
    "              # they create bindings between a target and an object.\n",
    "    \n",
    "    for e1 in newL1:\n",
    "        \n",
    "        print(len(L1))  # display mutation\n",
    "        print('L1=',L1)\n",
    "        \n",
    "        if e1 in L2:\n",
    "            L1.remove(e1)\n",
    "\n",
    "L1 = [1,2,3,4]\n",
    "L2 = [1,2,5,6]\n",
    "removeDups(L1, L2)\n",
    "print('\\n removeDups L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.2  list(L) returns a copy of the list L.\n",
    "\n",
    "* list(sequence) : return the new list from the sequence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "L1= [1, 2, 3, 4]\n",
      "3\n",
      "L1= [2, 3, 4]\n",
      "2\n",
      "L1= [3, 4]\n",
      "2\n",
      "L1= [3, 4]\n",
      "\n",
      " removeDups L1 = [3, 4]\n"
     ]
    }
   ],
   "source": [
    "def removeDups(L1, L2):\n",
    "    \"\"\"Assumes that L1 and L2 are lists.\n",
    "       Removes any element from L1 that also occurs in L2\"\"\"\n",
    "    \n",
    "    newL1=list(L1)  # a copy of the list L1\n",
    "    \n",
    "    for e1 in newL1:\n",
    "        \n",
    "        print(len(L1))  # display mutation\n",
    "        print('L1=',L1)\n",
    "        \n",
    "        if e1 in L2:\n",
    "            L1.remove(e1)\n",
    "\n",
    "L1 = [1,2,3,4]\n",
    "L2 = [1,2,5,6]\n",
    "removeDups(L1, L2)\n",
    "print('\\n removeDups L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.3  Shallow and deep copy\n",
    "\n",
    "Python: copy — Shallow and deep copy operations\n",
    "\n",
    "https://docs.python.org/3/library/copy.html\n",
    "\n",
    "`Assignment` statements in Python do not copy objects, they create `bindings` between a `target` and an `object`.\n",
    "\n",
    "For collections that are `mutable` or contain mutable items, a `copy` is sometimes needed so one can `change one copy` without changing the other.\n",
    "\n",
    "This module provides generic `shallow and deep copy` operations (explained below).\n",
    "\n",
    "**Interface summary:**\n",
    "\n",
    "* `copy.copy(x)`: Return a shallow copy of x.\n",
    "\n",
    "* `copy.deepcopy(x)`: Return a deep copy of x.\n",
    "\n",
    "The difference between shallow and deep copying is only relevant for `compound objects (objects that contain other objects`, like lists or class instances):\n",
    "\n",
    "* A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.\n",
    "\n",
    "* A deep copy constructs a new **compound** object and then, recursively, inserts copies into it of the objects found in the original.\n",
    "\n",
    "#### 6.3.1 The example of `copy.copy(x)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "def removeDups(L1, L2):\n",
    "    \"\"\"Assumes that L1 and L2 are lists.\n",
    "       Removes any element from L1 that also occurs in L2\"\"\"\n",
    "    \n",
    "    newL1=copy.copy(L1)  # a copy of the list L1\n",
    "    \n",
    "    for e1 in newL1:\n",
    "        \n",
    "        print(len(L1))  # display mutation\n",
    "        print('L1=',L1)\n",
    "        \n",
    "        if e1 in L2:\n",
    "            L1.remove(e1)\n",
    "\n",
    "L1 = [1,2,3,4]\n",
    "L2 = [1,2,5,6]\n",
    "removeDups(L1, L2)\n",
    "print('\\n removeDups L1 =', L1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 6.3.2 The example of `copy.deepcopy(x)`\n",
    "\n",
    "* https://github.com/PySEE/PyRankine"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4 Cloning Methods\n",
    "\n",
    "<strong style=\"color:blue;font-size:100%\">slicing：L1[:]</strong>\n",
    "\n",
    "<strong style=\"color:blue;font-size:100%\">list(L1)</strong>\n",
    "\n",
    "<strong style=\"color:blue;font-size:100%\">copy.copy(x)</strong>\n",
    "\n",
    "<strong style=\"color:blue;font-size:100%\">copy.deepcopy(x)</strong>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7 List Comprehension\n",
    "\n",
    "List comprehension provides a concise way to apply an operation to the values in a sequence.\n",
    "\n",
    "It creates `a new list` in which each element is the result of applying a given operation to a value from a sequence \n",
    "\n",
    "```python\n",
    "[expr for var in list]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 4, 9, 16, 25, 36]\n"
     ]
    }
   ],
   "source": [
    "L = [x**2 for x in range(1,7)]\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 4, 9, 16, 25, 36]\n"
     ]
    }
   ],
   "source": [
    "L =[]\n",
    "for x in range(1,7):\n",
    "    L.append(x**2)\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `for` clause in a list comprehension can be <b>followed</b> by one or more \n",
    "\n",
    "* <b>if </b> statements \n",
    "\n",
    "* <b>for</b> statements \n",
    "\n",
    "that are applied to the values produced by the `for` clause."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* `if` statements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 4, 9]\n"
     ]
    }
   ],
   "source": [
    "mixed = [1, 2, 'a', 3, 4.0]\n",
    "print([x**2 for x in mixed if type(x) == int])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* `for` statements "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 2, 4, 6, 3, 6, 9]\n"
     ]
    }
   ],
   "source": [
    "print([x*y for x in [1,2,3] for y in  [1,2,3]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Remember that somebody else may need to **read your code**\n",
    "\n",
    "* <b style=\"color:blue\">subtle</b>  is **not** usually a **desirable** property"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Further Reading：Python Tutorial\n",
    "\n",
    "* 5.1.3 List Comprehensions https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions\n",
    "\n",
    "* 5.1.4 Nested List Comprehensions https://docs.python.org/3/tutorial/datastructures.html#nested-list-comprehensions\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# B Sequence：Strings, Tuples, Lists and Range\n",
    "\n",
    "We have looked at three different sequence types: `str, tuple, and list`. \n",
    "\n",
    "* String：immutable characters\n",
    "\n",
    "* Tuple: immutable fix-sized array\n",
    "\n",
    "* List: mutable dynamic array\n",
    "\n",
    "* Range: an immutable sequence of numbers \n",
    "\n",
    "Some of their other similarities and differences are summarized in the Figure\n",
    "\n",
    "![fig57](./img/fig57.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 Common Operators and Functions on Sequence Types\n",
    "\n",
    "They are similar in that objects of of these types can be operated upon as described:\n",
    "\n",
    "* `e in seq` tests whether e is contained in the sequence.\n",
    "\n",
    "* `e not in seq` tests whether e is not contained in the sequence.\n",
    "\n",
    "* `seq1 + seq2`: concatenation, concatenates the two sequences. \n",
    "\n",
    "* `n*seq`: repetition,returns a sequence that repeats seq n times.\n",
    "\n",
    "* `seq[i], seq[-i]`: indexing,returns the ith/-ith element in the sequence.\n",
    "\n",
    "* `[m:n:step]`: slicing, returns a slice of the sequence.\n",
    "\n",
    "* `len(seq), min(seq), max(seq)`\n",
    "\n",
    "* `seq.index(e)` returns the index of the first occurrence of e in seq. Raises ValueError if e not\n",
    "in seq.\n",
    "\n",
    "* `seq.count(e)` returns the number of times that e occurs in  seq.\n",
    "\n",
    "* `for e  in seq`: iterates over the elements of the sequence\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 Built-in Methods of strings\n",
    "\n",
    "Since strings can contain only characters, there are <b>many built-in methods</b> that make life easy\n",
    "\n",
    "Keep in mind that since strings are immutable these all return values and have no side effect.\n",
    "<p>\n",
    "<img src=\"./img/fig58.PNG\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s='David Guttag plays basketball David'\n",
    "s.find('David')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "30"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# from the end of string\n",
    "s.rfind('David')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'David Guttag plays basketball'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s=\"David Guttag plays basketball     \"  # trailing whitespace space\n",
    "s.rstrip()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1  split\n",
    "\n",
    "One of the more useful built-in methods is `split`, which takes two strings as arguments. The second argument specifies a separator that is used to split the first argument into a sequence of substrings. For example,\n",
    "\n",
    "* s.split(d): Splits `s` using `d` as a delimiter\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['My', 'favorite', 'professor--John', 'G.--rocks']\n",
      "['My favorite professor', '', 'John G.', '', 'rocks']\n",
      "['My favorite professor', 'John G.', 'rocks']\n"
     ]
    }
   ],
   "source": [
    "print('My favorite professor--John G.--rocks'.split(' '))\n",
    "print('My favorite professor--John G.--rocks'.split('-'))\n",
    "print('My favorite professor--John G.--rocks'.split('--'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['David', 'Guttag', 'plays', 'basketball']"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s='David*Guttag*plays*basketball'\n",
    "s.split('*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2  whitespace  characters:\n",
    "\n",
    "The second argument is optional. If that argument is omitted the first string is split using arbitrary strings of whitespace characters (space, tab, newline, return, and formfeed).\n",
    "\n",
    "If `d` is omitted,\n",
    "```python\n",
    "s.split()\n",
    "```\n",
    "the substrings are seperated by  whitespace  characters:\n",
    "\n",
    "|space| tab |newline | return |formfeed|\n",
    "|:---:|----:|-------:|-------:|------:|\n",
    "|  space    |  \\t |  \\n  | \\r    |  \\f  |\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['David', 'Guttag', 'plays', 'basketball', 'whitespace', 'characters']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s='David\\t Guttag \\n plays\\r basketball\\f whitespace characters '\n",
    "s.split()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "David\t Guttag \n",
      " plays\r",
      " basketball\f",
      " whitespace characters \n"
     ]
    }
   ],
   "source": [
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 s.split(d) to read plain text files:\n",
    "\n",
    "* [Data Table Files](./Unit1-5-Files.ipynb)\n",
    "\n",
    "\n",
    "* [Unit2-3-UNDERSTANDING_EXPERIMENTAL_DATA](./Unit2-3-UNDERSTANDING_EXPERIMENTAL_DATA.ipynb)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Further Reading: Built-in Sequence Functions\n",
    "\n",
    "Python has a handful of useful sequence functions that you should familiarize yourself with and use at any opportunity.\n",
    "\n",
    "### 3.1 enumerate\n",
    "\n",
    "It’s common when iterating over a sequence to want to keep `track of the index` of the current item. \n",
    "\n",
    "A do-it-yourself approach would look like:\n",
    "\n",
    "```python\n",
    "i = 0\n",
    "for value in collection:\n",
    "    # do something with value\n",
    "    i += 1\n",
    "```\n",
    "Since this is so common, Python has a built-in function, `enumerate`, which returns a sequence of `(i, value)` tuples:\n",
    "```python\n",
    "for i, value in enumerate(collection):\n",
    "    # do something with value\n",
    "```\n",
    "When you are indexing data, a helpful pattern that uses` enumerate` is computing a `dict` mapping the values of a sequence (which are assumed to be unique) to their locations in the sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'foo': 0, 'bar': 1, 'baz': 2}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "some_list = ['foo', 'bar', 'baz']\n",
    "mapping = {}\n",
    "for i, v in enumerate(some_list):\n",
    "    mapping[v] = i\n",
    "mapping   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `sorted` function accepts the same arguments as the sort method on lists."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 zip\n",
    "\n",
    "`zip` “**pairs**” up the elements of a number of lists, tuples, or other sequences to create **a list of `tuples`**:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('foo', 'one'), ('bar', 'two'), ('baz', 'three')]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seq1 = ['foo', 'bar', 'baz']\n",
    "seq2 = ['one', 'two', 'three']\n",
    "zipped = zip(seq1, seq2)\n",
    "list(zipped)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`zip` can take an `arbitrary number` of sequences, and the number of elements it produces is determined by the `shortest` sequenc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('foo', 'one', False), ('bar', 'two', True)]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seq3 = [False, True]\n",
    "list(zip(seq1, seq2, seq3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A very common use of `zip` is `simultaneously iterating over multiple` sequences, possibly also combined with `enumerate`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: foo, one\n",
      "1: bar, two\n",
      "2: baz, three\n"
     ]
    }
   ],
   "source": [
    "for i, (a, b) in enumerate(zip(seq1, seq2)):\n",
    "    print('{0}: {1}, {2}'.format(i, a, b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Given a “zipped” sequence, `zip` can be applied in a clever way to “unzip” the sequence. Another way to think about this is converting a list of `rows` into a list of `columns`. The syntax, which looks a bit magical, is:\n",
    "\n",
    "List rows: ('Nolan', 'Ryan'), ('Roger', 'Clemens'),('Schilling', 'Curt')\n",
    "\n",
    "\n",
    "List columns:\n",
    "\n",
    " | first_names | last_names  |\n",
    " | ----------- |:-----------:|\n",
    " | Nolan       |   Ryan      |\n",
    " |  Roger      |  Clemens    | \n",
    " |Schilling    |  Curt       ||``\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('Nolan', 'Roger', 'Schilling')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'),('Schilling', 'Curt')]\n",
    "first_names, last_names = zip(*pitchers)\n",
    "first_names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('Ryan', 'Clemens', 'Curt')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "last_names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "165px"
   },
   "toc_section_display": true,
   "toc_window_display": false
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
